/****************************************************************************
 *   Copyright (C) 2008 by 7552                                             *
 *   fiubataller2-08c1@gruposyahoo.com.ar                                   *
 *                                                                          *
 *  Licensed under the Apache License, Version 2.0 (the "License");         *
 *  you may not use this file except in compliance with the License.        *
 *  You may obtain a copy of the License at                                 *
 *                                                                          *
 *      http://www.apache.org/licenses/LICENSE-2.0                          *
 *                                                                          *
 *  Unless required by applicable law or agreed to in writing, software     *
 *  distributed under the License is distributed on an "AS IS" BASIS,       *
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*
 *  See the License for the specific language governing permissions and     *
 *  limitations under the License.                                          *
 *                                                                          *
 ***************************************************************************/


#include "LogRecords.h"
#include <iostream>
using namespace Taller2::TransRec;


int CLogRecord::CreateRecord(fstream &f, CLogRecord* &record)
{
	record = NULL;
	LogEntryType et    = NONE;
	int origPos		   = f.tellg();
	f.read(reinterpret_cast<fstream::char_type*>(&et), sizeof(et));
	if (!f.fail()&& !f.bad())
	{
		f.seekg(origPos);
		try
		{
			if (et == CHECKPOINT)
                record = new CCheckPointRecord();
            else if (et == UPDATE)
                record = new CUpdateRecord();
            else if (et == DELETE)
                record = new CDeleteRecord();
            else if (et == INSERT)
                record = new CInsertRecord();
			else if (et == COMMIT)
				record = new CCommitRecord();
            else if (et == ROLLBACK)
				record = new CRollbackRecord();
		}catch(std::bad_alloc e)
		{
			return ERR_NO_MEMORY;
		};
		int result = record->Load(f);
		if (!IsSuccess(result))
		{
			delete record;
			record = NULL;
			f.seekg(origPos);
			return result;
		}else
			return NO_ERROR;
	}else
	{
		f.clear(); //reset the error flags
		f.seekg(origPos);
		return ERR_FILE_READING;
	};
};

//****************************************************************************

CLogRecord::CLogRecord()
{
	m_EntryType = NONE;
	m_LSN 		= -1;
	m_LastLSN 	= -1;
	m_timestamp = -1;
};

//****************************************************************************

CLogRecord::CLogRecord(LogEntryType et, int timestamp)
{
	m_EntryType = et;
	m_timestamp = timestamp;
	m_LSN = -1;
	m_LastLSN = -1;
};

//****************************************************************************

size_t CLogRecord::getSize()
{
	return sizeof(m_EntryType) + sizeof(m_LSN) + sizeof(m_LastLSN) + sizeof(m_timestamp);
};

//****************************************************************************

int CLogRecord::Load(fstream& f, bool allocStates)
{
	return NO_ERROR;
};

//****************************************************************************
//****************************************************************************
//****************************************************************************

CCheckPointRecord::CCheckPointRecord() : CLogRecord(CHECKPOINT, 0)
{};

//****************************************************************************

CCheckPointRecord::CCheckPointRecord(int timestamp) : CLogRecord(CHECKPOINT, timestamp)
{};

//****************************************************************************

int CCheckPointRecord::Load(fstream &f, bool allocStates)
{
	int result			 = NO_ERROR;
	size_t transListSize = 0;
	m_EntryType			 = CHECKPOINT;
	int origPos			 = f.tellg();

	f.read(reinterpret_cast<fstream::char_type*>(&m_LSN), sizeof(m_LSN));
	f.read(reinterpret_cast<fstream::char_type*>(&m_timestamp), sizeof(m_timestamp));
	f.read(reinterpret_cast<fstream::char_type*>(&transListSize), sizeof(transListSize));
	if (!f.bad() && !f.fail())
	{
		for (size_t i = 0; i < transListSize; i++)
		{
			int transID  = 0;
			int transLSN = 0;
			f.read(reinterpret_cast<fstream::char_type*>(&transID), sizeof(transID));
			f.read(reinterpret_cast<fstream::char_type*>(&transLSN), sizeof(transLSN));
			if (!f.bad() && !f.fail())
			{
				addTransaction(transID, transLSN);
			}else
			{
				f.clear();
				f.seekg(origPos);
				result = ERR_FILE_READING;
				m_tansList.clear(); // clear the list...
				break;
			};
		};
		if(IsSuccess(result))
		{
			f.read(reinterpret_cast<fstream::char_type*>(&m_LastLSN), sizeof(m_LastLSN));
			if (f.bad() || f.fail())
			{
				f.clear();
				f.seekg(origPos);
				result = ERR_FILE_READING;
				m_tansList.clear(); // clear the list...
			};
		};
	}else
	{
		f.clear();
		f.seekg(origPos);
		result = ERR_FILE_READING;
	};
	return result;
};

//****************************************************************************

CCheckPointRecord::~CCheckPointRecord()
{
	m_tansList.clear();
};

//****************************************************************************

void CCheckPointRecord::addTransaction(int TransactionID, int TransactionLSN)
{
	m_tansList[TransactionID] = TransactionLSN;
};

//****************************************************************************

size_t CCheckPointRecord::getSize()
{
	return CLogRecord::getSize() + sizeof(int) + 2*sizeof(CheckpointMap::size_type)*m_tansList.size();
};

//****************************************************************************

int CCheckPointRecord::serialize(char* &pBuffer)
{
	pBuffer					= NULL;
	size_t size				= getSize();
	size_t transListSize	= m_tansList.size();

	try
	{
		pBuffer = new char[size];
	}catch(std::bad_alloc e)
	{
		return ERR_NO_MEMORY;
	};

	char* p = pBuffer;

	memcpy(p, &m_EntryType, sizeof(m_EntryType)); p += sizeof(m_EntryType);
	memcpy(p, &m_LSN, sizeof(m_LSN)); p += sizeof(m_LSN);
	memcpy(p, &m_timestamp, sizeof(m_timestamp)); p += sizeof(m_timestamp);
	memcpy(p, &transListSize, sizeof(transListSize)); p += sizeof(transListSize);

	for (CheckpointMap::iterator it = m_tansList.begin(); it != m_tansList.end(); it++)
	{
		int ID  = it->first;
		int LSN = it->second;
		memcpy(p, &ID, sizeof(ID)); p += sizeof(ID);
		memcpy(p, &LSN, sizeof(LSN)); p += sizeof(LSN);
	};
	memcpy(p, &m_LastLSN, sizeof(m_LastLSN));

	return NO_ERROR;
};

//****************************************************************************

int CCheckPointRecord::appendToFile(fstream &f)
{
	char *buffer = NULL;
	int result = serialize(buffer);
	if (IsSuccess(result))
	{
		int origPos = f.tellp();
		f.seekp(0, ios_base::end);
		f.clear();
		f.write(buffer, getSize());
		if (!f.bad() && !f.fail())
		{
			f.flush();
			delete[] buffer;
			result = NO_ERROR;
		}else
		{
			f.clear();
			f.seekp(origPos);
			delete[] buffer;
			result = ERR_FILE_WRITING;
		};
	}else
		result = ERR_NO_MEMORY;

	return result;
};

//****************************************************************************

CCheckPointRecord::CheckpointMap CCheckPointRecord::GetTransactionMap()
{
	return m_tansList;
};

//****************************************************************************
//****************************************************************************
//****************************************************************************

CBasicOperationRecord::CBasicOperationRecord()
{
	CLogRecord(NONE, 0);
	m_TransactionID = 0;
	m_lastLSNsameTransaction = -1;
};

//****************************************************************************

CBasicOperationRecord::CBasicOperationRecord(int ID, LogEntryType et, int timestamp)
{
	CLogRecord(et, timestamp);
	m_TransactionID = ID;
	m_lastLSNsameTransaction = -1;

	m_EntryType=et; 
};

//****************************************************************************

size_t CBasicOperationRecord::getSize()
{
	return CLogRecord::getSize() + sizeof(m_lastLSNsameTransaction) + sizeof(m_TransactionID);
};

//****************************************************************************

int CBasicOperationRecord::serialize(char* &pBuffer)
{
	size_t size = getSize();
	//m_LSN = m_LastLSN+size;

	pBuffer = NULL;
	try
	{
		pBuffer = new char[size];
	}catch(std::bad_alloc e)
	{
		return ERR_NO_MEMORY;
	};
	char* p = pBuffer;

	memcpy(p, &m_EntryType, sizeof(m_EntryType)); p += sizeof(m_EntryType);
	memcpy(p, &m_LSN, sizeof(m_LSN)); p += sizeof(m_LSN);
	memcpy(p, &m_lastLSNsameTransaction, sizeof(m_lastLSNsameTransaction)); p += sizeof(m_lastLSNsameTransaction);
	memcpy(p, &m_timestamp, sizeof(m_timestamp)); p += sizeof(m_timestamp);
	memcpy(p, &m_TransactionID, sizeof(m_TransactionID)); p += sizeof(m_TransactionID);
	memcpy(p, &m_LastLSN, sizeof(m_LastLSN));

	return NO_ERROR;
};

//****************************************************************************

int CBasicOperationRecord::appendToFile(fstream &f)
{
	char *buffer = NULL;
	int result = serialize(buffer);

	if (IsSuccess(result))
	{
		int origPos = f.tellp();
		f.seekp(0, ios_base::end);
		f.clear();
		f.write(buffer, getSize());
		if (!f.bad() && !f.fail())
		{
			f.flush();
			delete[] buffer;
			result = NO_ERROR;
		}else
		{
			f.clear();
			f.seekp(origPos);
			delete[] buffer;
			result = ERR_FILE_WRITING;
		};
	}else
		result = ERR_NO_MEMORY;

	return result;
};

//****************************************************************************
//****************************************************************************
//****************************************************************************

CRollbackRecord::CRollbackRecord() : CBasicOperationRecord(0, ROLLBACK, 0)
{};

//****************************************************************************

CRollbackRecord::CRollbackRecord( int ID, int timestamp) : CBasicOperationRecord(ID, ROLLBACK, timestamp)
{};

//****************************************************************************

int CRollbackRecord::Load(fstream &f, bool allocStates)
{
	int origPos = f.tellg();
	m_EntryType = ROLLBACK;
	f.read(reinterpret_cast<fstream::char_type*>(&m_LSN), sizeof(m_LSN));
	f.read(reinterpret_cast<fstream::char_type*>(&m_lastLSNsameTransaction), sizeof(m_lastLSNsameTransaction));
	f.read(reinterpret_cast<fstream::char_type*>(&m_timestamp), sizeof(m_timestamp));
	f.read(reinterpret_cast<fstream::char_type*>(&m_TransactionID), sizeof(m_TransactionID));
	f.read(reinterpret_cast<fstream::char_type*>(&m_LastLSN), sizeof(m_LastLSN));
	if (f.bad() || f.fail())
	{
		f.clear();
		f.seekg(origPos);
		return ERR_FILE_READING;
	};
	return NO_ERROR;
};

//****************************************************************************
//****************************************************************************
//****************************************************************************

CCommitRecord::CCommitRecord() : CBasicOperationRecord(0, COMMIT, 0)
{};

//****************************************************************************

CCommitRecord::CCommitRecord( int ID, int timestamp) : CBasicOperationRecord(ID, COMMIT, timestamp)
{};

//****************************************************************************

int CCommitRecord::Load(fstream &f, bool allocStates)
{
	m_EntryType = COMMIT;
	int origPos = f.tellg();
	f.seekg((int)f.tellg() + sizeof(m_EntryType));
	f.read(reinterpret_cast<fstream::char_type*>(&m_LSN), sizeof(m_LSN));
	f.read(reinterpret_cast<fstream::char_type*>(&m_lastLSNsameTransaction), sizeof(m_lastLSNsameTransaction));
	f.read(reinterpret_cast<fstream::char_type*>(&m_timestamp), sizeof(m_timestamp));
	f.read(reinterpret_cast<fstream::char_type*>(&m_TransactionID), sizeof(m_TransactionID));
	f.read(reinterpret_cast<fstream::char_type*>(&m_LastLSN), sizeof(m_LastLSN));
	if (f.bad() || f.fail())
	{
		f.clear();
		f.seekg(origPos);
		return ERR_FILE_READING;
	};
	return NO_ERROR;
};

//****************************************************************************
//****************************************************************************
//****************************************************************************

CInsertRecord::CInsertRecord() :CBasicOperationRecord(0, INSERT, 0),
	  							m_ObjectID(0),
								m_NewObjectSize(0),
								m_Object(0)
{};

//****************************************************************************

CInsertRecord::CInsertRecord(int ID, int timestamp, long long ObjectID) :
	  							CBasicOperationRecord(ID, INSERT, timestamp),
	  							m_ObjectID(ObjectID),
								m_NewObjectSize(0),
								m_Object(0)
{};

//****************************************************************************

int CInsertRecord::SetState(const char* object, int objectSize)
{
	m_NewObjectSize = objectSize;
	try
	{
		m_Object = new char[m_NewObjectSize];
	}catch(std::bad_alloc e)
	{
		return ERR_NO_MEMORY;
	};

	memcpy(m_Object, object, m_NewObjectSize);
	return NO_ERROR;
};

//****************************************************************************

int CInsertRecord::Load(fstream &f, bool allocObject)
{
	m_EntryType = INSERT;
	int origPos = f.tellg();

	f.seekg(sizeof(LogEntryType), ios_base::cur);
	f.read(reinterpret_cast<fstream::char_type*>(&m_LSN), sizeof(m_LSN));
	f.read(reinterpret_cast<fstream::char_type*>(&m_lastLSNsameTransaction), sizeof(m_lastLSNsameTransaction));
	f.read(reinterpret_cast<fstream::char_type*>(&m_timestamp), sizeof(m_timestamp));
	f.read(reinterpret_cast<fstream::char_type*>(&m_TransactionID), sizeof(m_TransactionID));
	f.read(reinterpret_cast<fstream::char_type*>(&m_ObjectID), sizeof(m_ObjectID));
	f.seekg(sizeof(int), ios_base::cur); // No hay oldObjectSize... Se escribe siempre en 0
	f.read(reinterpret_cast<fstream::char_type*>(&m_NewObjectSize), sizeof(m_NewObjectSize));

	if (!f.bad() && !f.fail())
	{
		if (allocObject)
		{
			try
			{
				m_Object = new char[m_NewObjectSize];
			}catch(std::bad_alloc e)
			{
				f.seekg(origPos);
				return ERR_NO_MEMORY;
			};
			f.read(reinterpret_cast<fstream::char_type*>(m_Object), m_NewObjectSize);
		}else
		{
			f.seekg(m_NewObjectSize, ios_base::cur);
			m_Object = 0;
		};
		f.read(reinterpret_cast<fstream::char_type*>(&m_LastLSN), sizeof(m_LastLSN));
		if (f.bad() || f.fail())
		{
			if (m_Object)
				delete[] m_Object;
			f.clear();
			f.seekg(origPos);
			return ERR_FILE_READING;
		};
	}else
	{
		f.clear();
		f.seekg(origPos);
		return ERR_FILE_READING;
	};
	return NO_ERROR;
};

//****************************************************************************

CInsertRecord::~CInsertRecord()
{
	if (m_Object)
	{
		delete[] m_Object;
		m_Object = 0;
	};
};

//****************************************************************************

size_t CInsertRecord::getSize()
{
//	return CBasicOperationRecord::getSize() + sizeof(m_ObjectID) + sizeof(m_NewObjectSize) + sizeof(int) +m_NewObjectSize;
	return CBasicOperationRecord::getSize() + sizeof(m_ObjectID) + sizeof(m_NewObjectSize) + m_NewObjectSize;
};

//****************************************************************************
int CInsertRecord::serialize(char* &pBuffer)
{
	size_t size = getSize();
	//m_LSN=m_LastLSN+size;

	pBuffer = NULL;
	try
	{
		pBuffer = new char[size];
	}catch(std::bad_alloc e)
	{
		return ERR_NO_MEMORY;
	};
	char* p = pBuffer;

	memset(p, 0, size);

memcpy(p, &m_EntryType, sizeof(m_EntryType));
//cout<<"ET: REAL: "<<m_EntryType<<" GRABADO: "<<(LogEntryType)(*p)<<" Tam: "<<sizeof(m_EntryType) <<endl;
 p += sizeof(m_EntryType);

	memcpy(p, &m_LSN, sizeof(m_LSN));
//	cout<<"LSN: REAL: "<<m_LSN<<" GRABADO: "<<(int)(*p)<<" Tam: "<<sizeof(m_LSN) <<endl;
	p += sizeof(m_LSN);
	memcpy(p, &m_lastLSNsameTransaction, sizeof(m_lastLSNsameTransaction));
//	cout<<"LSN ST: REAL: "<<m_lastLSNsameTransaction<<" GRABADO: "<<(int)(*p)<<" Tam: "<<sizeof(m_lastLSNsameTransaction) <<endl;
	p += sizeof(m_lastLSNsameTransaction);
	memcpy(p, &m_timestamp, sizeof(m_timestamp));
//	cout<<"TIME: REAL: "<<m_timestamp<<" GRABADO: "<<(int)(*p)<<" Tam: "<<sizeof(m_timestamp) <<endl;
	p += sizeof(m_timestamp);
	memcpy(p, &m_TransactionID, sizeof(m_TransactionID));
//	cout<<"TID: REAL: "<<m_TransactionID<<" GRABADO: "<<(int)(*p)<<" Tam: "<<sizeof(m_TransactionID) <<endl;
	p += sizeof(m_TransactionID);
	memcpy(p, &m_ObjectID, sizeof(m_ObjectID));
//	cout<<"OID: REAL: "<<m_ObjectID<<" GRABADO: "<<(int)(*p)<<" Tam: "<<sizeof(m_ObjectID) <<endl;
	p += sizeof(m_ObjectID);
	memcpy(p, &m_NewObjectSize, sizeof(m_NewObjectSize));
//	cout<<"OS: REAL: "<<m_NewObjectSize<<" GRABADO: "<<(int)(*p)<<" Tam: "<<sizeof(m_NewObjectSize) <<endl;
	p += sizeof(m_NewObjectSize);
	memcpy(p, m_Object, m_NewObjectSize);
//	cout<<"OS: REAL: "<<m_Object<<" GRABADO: "<<(int)(*p)<<" Tam: "<<m_NewObjectSize <<endl;
	p += m_NewObjectSize;
	memcpy(p, &m_LastLSN, sizeof(m_LastLSN));p+=sizeof(m_LastLSN);
//	cout<<"REAL: "<<m_LastLSN<<"GRABADO: "<<(int)(*p)<<" Tam: "<<sizeof(int)<<endl;
//	cout<<"TAM LR: "<<  CLogRecord::getSize()<<endl;
//	cout<<"TAM BO: "<<	CBasicOperationRecord::getSize()<<endl;
//	cout<<"TAM IR: "<< sizeof(m_ObjectID) + sizeof(m_NewObjectSize) +m_NewObjectSize<<endl;
//	cout<<"TAM TOT: "<<size<<endl;
//	cout<<"TAM US: "<<(int)p-(int)pBuffer<<endl;
	return NO_ERROR;
};

//****************************************************************************

int CInsertRecord::appendToFile(fstream &f)
{
	char *buffer = NULL;
	int result = serialize(buffer);
	if (IsSuccess(result))
	{
		int origPos = f.tellp();
		f.seekp(0, ios_base::end);
		f.clear();
		f.write(buffer, getSize());
		if (!f.bad() && !f.fail())
		{
			f.flush();
			delete[] buffer;
			result = NO_ERROR;
		}else
		{
			f.clear();
			f.seekp(origPos);
			delete[] buffer;
			result = ERR_FILE_WRITING;
		};
	}else
		result = ERR_NO_MEMORY;

	return result;
};

//****************************************************************************
//****************************************************************************
//****************************************************************************

CUpdateRecord::CUpdateRecord() :CBasicOperationRecord(0, UPDATE, 0){
	m_ObjectID = 0;
	m_newObjectSize = 0;
	m_newObject = 0;
	m_oldObjectSize = 0;
	m_oldObject = 0;
};

//****************************************************************************

CUpdateRecord::CUpdateRecord(int ID, int timestamp, long long ObjectID) :CBasicOperationRecord(ID, UPDATE, timestamp){
	m_ObjectID = ObjectID;
	m_newObjectSize = 0;
	m_newObject = 0;
	m_oldObjectSize = 0;
	m_oldObject = 0;
};

//****************************************************************************

int CUpdateRecord::SetState(const char* oldObject, int oldObjectSize,
							const char* newObject, int newObjectSize)
{
	m_newObjectSize = newObjectSize;
	m_oldObjectSize = oldObjectSize;
	try
	{
		m_oldObject = new char[m_oldObjectSize];
	}catch(std::bad_alloc e)
	{
		return ERR_NO_MEMORY;
	};

	try
	{
		m_newObject = new char[m_newObjectSize];
	}catch(std::bad_alloc e)
	{
		if (m_oldObject)
			delete[] m_oldObject;
		return ERR_NO_MEMORY;
	};

	memcpy(m_oldObject, oldObject, m_oldObjectSize);
	memcpy(m_newObject, newObject, m_newObjectSize);

	return NO_ERROR;
};

//****************************************************************************

int CUpdateRecord::Load(fstream &f, bool allocObject)
{
	m_EntryType = UPDATE;
	int origPos = f.tellg();

	f.seekg(sizeof(LogEntryType), ios_base::cur);
	f.read(reinterpret_cast<fstream::char_type*>(&m_LSN), sizeof(m_LSN));
	f.read(reinterpret_cast<fstream::char_type*>(&m_lastLSNsameTransaction), sizeof(m_lastLSNsameTransaction));
	f.read(reinterpret_cast<fstream::char_type*>(&m_timestamp), sizeof(m_timestamp));
	f.read(reinterpret_cast<fstream::char_type*>(&m_TransactionID), sizeof(m_TransactionID));
	f.read(reinterpret_cast<fstream::char_type*>(&m_ObjectID), sizeof(m_ObjectID));
	f.read(reinterpret_cast<fstream::char_type*>(&m_oldObjectSize), sizeof(m_oldObjectSize));
	f.read(reinterpret_cast<fstream::char_type*>(&m_newObjectSize), sizeof(m_newObjectSize));

	if (!f.bad() && !f.fail())
	{
		if (allocObject)
		{
			try
			{
				m_oldObject = new char[m_oldObjectSize];
			}catch(std::bad_alloc e)
			{
				f.seekg(origPos);
				return ERR_NO_MEMORY;
			};
			try
			{
				m_newObject = new char[m_newObjectSize];
			}catch(std::bad_alloc e)
			{
				if (m_oldObject)
					delete[] m_oldObject;
				f.seekg(origPos);
				return ERR_NO_MEMORY;

			};
			f.read(reinterpret_cast<fstream::char_type*>(m_oldObject), m_oldObjectSize);
			f.read(reinterpret_cast<fstream::char_type*>(m_newObject), m_newObjectSize);
		}else
		{
			f.seekg(m_oldObjectSize + m_newObjectSize, ios_base::cur);
			m_newObject = 0;
			m_oldObject = 0;
		};
		f.read(reinterpret_cast<fstream::char_type*>(&m_LastLSN), sizeof(m_LastLSN));
		if (f.bad() || f.fail())
		{
			if (m_oldObject)
				delete[] m_oldObject;
			if(m_newObject)
				delete[] m_newObject;
			f.clear();
			f.seekg(origPos);
			return ERR_FILE_READING;
		};
	}else
	{
		f.clear();
		f.seekg(origPos);
		return ERR_FILE_READING;
	};
	return NO_ERROR;
};

//****************************************************************************

CUpdateRecord::~CUpdateRecord()
{
	if (m_newObject)
	{
		delete[] m_newObject;
		m_newObject = 0;
	};
	if(m_oldObject)
	{
		delete[] m_oldObject;
		m_oldObject = 0;
	};
};

//****************************************************************************

size_t CUpdateRecord::getSize()
{
	return CBasicOperationRecord::getSize() + sizeof(m_ObjectID) + sizeof(m_newObjectSize) +
		sizeof(m_oldObjectSize) + m_oldObjectSize + m_newObjectSize;
};

//****************************************************************************

int CUpdateRecord::serialize(char* &pBuffer)
{
	size_t size = getSize();
	//m_LSN=m_LastLSN+size;

	pBuffer = NULL;
	try
	{
		pBuffer = new char[size];
	}catch(std::bad_alloc e)
	{
		return ERR_NO_MEMORY;
	};
	char* p = pBuffer;

	memset(p, 0, size);
	memcpy(p, &m_EntryType, sizeof(m_EntryType)); p += sizeof(m_EntryType);
	memcpy(p, &m_LSN, sizeof(m_LSN)); p += sizeof(m_LSN);
	memcpy(p, &m_lastLSNsameTransaction, sizeof(m_lastLSNsameTransaction)); p += sizeof(m_lastLSNsameTransaction);
	memcpy(p, &m_timestamp, sizeof(m_timestamp)); p += sizeof(m_timestamp);
	memcpy(p, &m_TransactionID, sizeof(m_TransactionID)); p += sizeof(m_TransactionID);
	memcpy(p, &m_ObjectID, sizeof(m_ObjectID)); p += sizeof(m_ObjectID);
	memcpy(p, &m_oldObjectSize, sizeof(m_oldObjectSize)); p += sizeof(m_oldObjectSize);
	memcpy(p, &m_newObjectSize, sizeof(m_newObjectSize)); p += sizeof(m_newObjectSize);
	memcpy(p, m_oldObject, m_oldObjectSize); p += m_oldObjectSize;
	memcpy(p, m_newObject, m_newObjectSize); p += m_newObjectSize;
	memcpy(p, &m_LastLSN, sizeof(m_LastLSN));

	return NO_ERROR;
};

//****************************************************************************

int CUpdateRecord::appendToFile(fstream &f)
{
	char *buffer = NULL;
	int result = serialize(buffer);

	if (IsSuccess(result))
	{
		int origPos = f.tellp();
		f.seekp(0, ios_base::end);
		f.clear();
		f.write(buffer, getSize());
		if (!f.bad() && !f.fail())
		{
			f.flush();
			delete[] buffer;
			result = NO_ERROR;
		}else
		{
			f.clear();
			f.seekp(origPos);
			delete[] buffer;
			result = ERR_FILE_WRITING;
		};
	};
	return result;
};

//****************************************************************************
//****************************************************************************
//****************************************************************************

CDeleteRecord::CDeleteRecord() : CBasicOperationRecord(0, DELETE, 0),
	  							m_ObjectID(0),
								m_oldObjectSize(0),
								m_Object(0)
{};

//****************************************************************************

CDeleteRecord::CDeleteRecord(int ID, int timestamp, long long ObjectID) :
	  							CBasicOperationRecord(ID, DELETE, timestamp),
	  							m_ObjectID(ObjectID),
								m_oldObjectSize(0),
								m_Object(0)
{};

//****************************************************************************

int CDeleteRecord::SetState(const char* object, int objectSize)
{
	m_oldObjectSize = objectSize;
	try
	{
		m_Object = new char[m_oldObjectSize];
	}catch(std::bad_alloc e)
	{
		return ERR_NO_MEMORY;
	};

	memcpy(m_Object, object, m_oldObjectSize);
	return NO_ERROR;
};
//****************************************************************************

int CDeleteRecord::Load(fstream &f, bool allocObject)
{
	m_EntryType = DELETE;
	int origPos = f.tellg();

	f.seekg(sizeof(LogEntryType), ios_base::cur);
	f.read(reinterpret_cast<fstream::char_type*>(&m_LSN), sizeof(m_LSN));
	f.read(reinterpret_cast<fstream::char_type*>(&m_lastLSNsameTransaction), sizeof(m_lastLSNsameTransaction));
	f.read(reinterpret_cast<fstream::char_type*>(&m_timestamp), sizeof(m_timestamp));
	f.read(reinterpret_cast<fstream::char_type*>(&m_TransactionID), sizeof(m_TransactionID));
	f.read(reinterpret_cast<fstream::char_type*>(&m_ObjectID), sizeof(m_ObjectID));
	f.read(reinterpret_cast<fstream::char_type*>(&m_oldObjectSize), sizeof(m_oldObjectSize));
	f.seekg(sizeof(int), ios_base::cur); // no hay newObjectSize... se escribe siempre en 0

	if (!f.bad() && !f.fail())
	{
		if (allocObject)
		{
			try
			{
				m_Object = new char[m_oldObjectSize];
			}catch(std::bad_alloc e)
			{
				f.seekg(origPos);
				return ERR_NO_MEMORY;
			};
			f.read(reinterpret_cast<fstream::char_type*>(m_Object), m_oldObjectSize);
		}else
		{
			f.seekg(m_oldObjectSize,ios_base::cur);
			m_Object = 0;
		};
		f.read(reinterpret_cast<fstream::char_type*>(&m_LastLSN), sizeof(m_LastLSN));
		if (f.bad() || f.fail())
		{
			if (m_Object)
				delete[] m_Object;
			f.clear();
			f.seekg(origPos);
			return ERR_FILE_READING;
		};
	}else
	{
		f.clear();
		f.seekg(origPos);
		return ERR_FILE_READING;
	};
	return NO_ERROR;
};

//****************************************************************************

CDeleteRecord::~CDeleteRecord()
{
	if (m_Object)
	{
		delete[] m_Object;
		m_Object = 0;
	};
};

//****************************************************************************

size_t CDeleteRecord::getSize()
{
//	return CBasicOperationRecord::getSize() + sizeof(m_ObjectID) + sizeof(m_oldObjectSize) + sizeof(int) +m_oldObjectSize;
	return CBasicOperationRecord::getSize() + sizeof(m_ObjectID) + sizeof(m_oldObjectSize) + m_oldObjectSize;
};

//****************************************************************************

int CDeleteRecord::serialize(char* &pBuffer)
{
	size_t size = getSize();
	pBuffer = NULL;
	try
	{
		pBuffer = new char[size];
	}catch(std::bad_alloc e)
	{
		return ERR_NO_MEMORY;
	};
	char* p = pBuffer;
	//m_LSN=m_LastLSN+size;

	memset(p, 0, size);
	memcpy(p, &m_EntryType, sizeof(m_EntryType));
	cout<<"ENTRY: "<<m_EntryType<<endl;
	p += sizeof(m_EntryType);
	memcpy(p, &m_LSN, sizeof(m_LSN)); p += sizeof(m_LSN);
	memcpy(p, &m_lastLSNsameTransaction, sizeof(m_lastLSNsameTransaction)); p += sizeof(m_lastLSNsameTransaction);
	memcpy(p, &m_timestamp, sizeof(m_timestamp)); p += sizeof(m_timestamp);
	memcpy(p, &m_TransactionID, sizeof(m_TransactionID)); p += sizeof(m_TransactionID);
	memcpy(p, &m_ObjectID, sizeof(m_ObjectID)); p += sizeof(m_ObjectID);
	memcpy(p, &m_oldObjectSize, sizeof(m_oldObjectSize)); p += sizeof(m_oldObjectSize);
	//p += sizeof(int);
	memcpy(p, m_Object, m_oldObjectSize); p += m_oldObjectSize;
	memcpy(p, &m_LastLSN, sizeof(m_LastLSN));p += sizeof(m_LastLSN);
//    cout<<"TAM: "<<size<<" Real: "<<(int)p-(int)pBuffer<<endl;
	return NO_ERROR;
};

//****************************************************************************

int CDeleteRecord::appendToFile(fstream &f)
{
	char *buffer = NULL;
	int result = serialize(buffer);
	if (IsSuccess(result))
	{
		int origPos = f.tellp();
		f.seekp(0, ios_base::end);
		f.clear();
		f.write(buffer, getSize());
		if (!f.bad() && !f.fail())
		{
			f.flush();
			delete[] buffer;
			result = NO_ERROR;
		}else
		{
			f.clear();
			f.seekp(origPos);
			delete[] buffer;
			result = ERR_FILE_WRITING;
		}
	};

	return result;
};

//****************************************************************************
//****************************************************************************
//****************************************************************************
